package images;

import java.awt.Color;
import org.lwjgl.opengl.*;
import org.newdawn.slick.opengl.Texture;

/**
 *
 * @author Luan
 */
public class ImageInfo {

    private int x, y, w, h;
    private float ang;
    private double txi, txf, tyi, tyf;

    public ImageInfo(int w, int h, float propX, float propY) {
        this(0, 0, w, h, 0, propX, propY);
    }

    public ImageInfo(int x, int y, int w, int h, float ang, double propX, double propY) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.ang = ang;

        this.generateTexCoords(propX, propY);
    }

    public final void generateTexCoords(double col, double lin) {
        txi = x * col;
        txf = (x + w) * col;
        tyi = y * lin;
        tyf = (y + h) * lin;
    }

    public int getHeight() {
        return h;
    }

    public int getWidth() {
        return w;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public float getAngle() {
        return ang;
    }

    public void setAngle(float ang) {
        this.ang = ang;
    }

    public void draw(int dx, int dy) {
        draw(dx, dy, ang);
    }
    
    public void drawHMirror(int dx, int dy) {
        GL11.glPushMatrix();
        rotate(dx, dy, w, h, ang);
        drawHMirror(dx, dy, w, h);        
        GL11.glPopMatrix();
    }
    
    public void drawHVMirror(int dx, int dy) {
        GL11.glPushMatrix();
        rotate(dx, dy, w, h, ang);
        drawHVMirror(dx, dy, w, h);        
        GL11.glPopMatrix();
    }
    
    public void drawVMirror(int dx, int dy) {
        GL11.glPushMatrix();
        rotate(dx, dy, w, h, ang);
        drawVMirror(dx, dy, w, h);        
        GL11.glPopMatrix();
    }

    public void draw(int dx, int dy, int dw, int dh) {
        draw(dx, dy, dw, dh, ang);
    }

    public void draw(int dx, int dy, float ang) {
        draw(dx, dy, w, h, ang);
    }
    
    public void drawAngle(int dx, int dy, float ang) {
        draw(dx, dy, this.ang + ang);
    }
    
    public void drawAngle(int dx, int dy, int dw, int dh, float ang) {
        draw(dx, dy, dw, dh, this.ang + ang);
    }

    public void draw(int dx, int dy, int dw, int dh, float ang) {
        GL11.glPushMatrix();
        rotate(dx, dy, dw, dh, ang);
        drawRect(dx, dy, dw, dh);
        GL11.glPopMatrix();
    }
    
    public static void rotate(float ang, int cx, int cy) {
        if (ang != 0) {
            GL11.glTranslatef(cx, cy, 0);
            GL11.glRotatef(ang, 0, 0, 1);
            GL11.glTranslatef(-cx, -cy, 0);
        }
    }
    
    public static void flipHorizontal() {
        GL11.glScalef(-1, 1, 1);
    }

    public static void rotate(int dx, int dy, int dw, int dh, float ang) {
        if (ang != 0) {
            int rx = dx + dw / 2, ry = dy + dh / 2;
            GL11.glTranslatef(rx, ry, 0);
            GL11.glRotatef(ang, 0, 0, 1);
            GL11.glTranslatef(-rx, -ry, 0);
        }
    }

    public void drawRect(int dx, int dy) {
        drawRect(dx, dy, w, h);
    }
    
    public void drawHMirror(int dx, int dy, int dw, int dh) {
        GL11.glBegin(GL11.GL_QUADS);
        {
            GL11.glTexCoord2d(txf, tyi);
            GL11.glVertex2i(dx, dy);
            GL11.glTexCoord2d(txi, tyi);
            GL11.glVertex2i(dx + dw, dy);
            GL11.glTexCoord2d(txi, tyf);
            GL11.glVertex2i(dx + dw, dy + dh);
            GL11.glTexCoord2d(txf, tyf);
            GL11.glVertex2i(dx, dy + dh);
        }
        GL11.glEnd();
    }
    
    public void drawVMirror(int dx, int dy, int dw, int dh) {
        GL11.glBegin(GL11.GL_QUADS);
        {
            GL11.glTexCoord2d(txi, tyf);
            GL11.glVertex2i(dx, dy);
            GL11.glTexCoord2d(txf, tyf);
            GL11.glVertex2i(dx + dw, dy);
            GL11.glTexCoord2d(txf, tyi);
            GL11.glVertex2i(dx + dw, dy + dh);
            GL11.glTexCoord2d(txi, tyi);
            GL11.glVertex2i(dx, dy + dh);
        }
        GL11.glEnd();
    }

    public void drawHVMirror(int dx, int dy, int dw, int dh) {
        GL11.glBegin(GL11.GL_QUADS);
        {
            GL11.glTexCoord2d(txf, tyf);
            GL11.glVertex2i(dx, dy);
            GL11.glTexCoord2d(txi, tyf);            
            GL11.glVertex2i(dx + dw, dy);
            GL11.glTexCoord2d(txi, tyi);
            GL11.glVertex2i(dx + dw, dy + dh);
            GL11.glTexCoord2d(txf, tyi);
            GL11.glVertex2i(dx, dy + dh);
        }
        GL11.glEnd();
    }

    public void drawRect(int dx, int dy, int dw, int dh) {
        GL11.glBegin(GL11.GL_QUADS);
        {
            GL11.glTexCoord2d(txi, tyi);
            GL11.glVertex2i(dx, dy);
            GL11.glTexCoord2d(txf, tyi);
            GL11.glVertex2i(dx + dw, dy);
            GL11.glTexCoord2d(txf, tyf);
            GL11.glVertex2i(dx + dw, dy + dh);
            GL11.glTexCoord2d(txi, tyf);
            GL11.glVertex2i(dx, dy + dh);
        }
        GL11.glEnd();
    }

    public static void draw(int x, int y, Texture t) {
        draw(x, y, t.getImageWidth(), t.getImageHeight(), t);
    }

    public static void draw(int x, int y, int w, int h, Texture t) {
        t.bind();
        
        GL11.glBegin(GL11.GL_QUADS);
        {
            GL11.glTexCoord2d(0, 0);
            GL11.glVertex2i(x, y);
            GL11.glTexCoord2d(t.getWidth(), 0);
            GL11.glVertex2i(x + w, y);
            GL11.glTexCoord2d(t.getWidth(), t.getHeight());
            GL11.glVertex2i(x + w, y + h);
            GL11.glTexCoord2d(0, t.getHeight());
            GL11.glVertex2i(x, y + h);
        }
        GL11.glEnd();
    }
    
    public static void drawColorSquare(int x, int y, int w, int h, Color c) {
        drawColorSquare(x, y, w, h, c, true);
    }
    
    public static void drawColorSquare(int x, int y, int w, int h, Color c, boolean filled) {
        c = fixColor(c);
        GL11.glColor3f((float) c.getRed()/255, (float) c.getGreen()/255, (float) c.getBlue()/255);
        GL11.glDisable(GL11.GL_TEXTURE_2D);
        GL11.glBegin(filled ? GL11.GL_QUADS : GL11.GL_LINE_LOOP);
        {
            GL11.glVertex2i(x, y);
            GL11.glVertex2i(x + w, y);
            GL11.glVertex2i(x + w, y + h);
            GL11.glVertex2i(x, y + h);
        }
        GL11.glEnd();
        GL11.glColor3f(1.0f, 1.0f, 1.0f);
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        if (ImageManager.isGrayBinded())
            ImageManager.bindGray();
    }
    
    public static void drawOctagon(int x, int y, int w, int h, Color c, int k) {
        c = fixColor(c);
        GL11.glColor3f((float) c.getRed()/255, (float) c.getGreen()/255, (float) c.getBlue()/255);
        GL11.glDisable(GL11.GL_TEXTURE_2D);
        GL11.glLineWidth(3);
        GL11.glBegin(GL11.GL_LINE_LOOP);
        {
            GL11.glVertex2i(x - k, y + k);
            GL11.glVertex2i(x + k, y - k);
            
            GL11.glVertex2i(x + w - k, y - k);
            GL11.glVertex2i(x + w + k, y + k);
            
            GL11.glVertex2i(x + w + k, y + h - k);
            GL11.glVertex2i(x + w - k, y + h + k);
            
            GL11.glVertex2i(x + k, y + h + k);
            GL11.glVertex2i(x - k, y + h - k);
        }
        GL11.glEnd();
        GL11.glLineWidth(1);
        GL11.glColor3f(1.0f, 1.0f, 1.0f);
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        if (ImageManager.isGrayBinded())
            ImageManager.bindGray();
    }
    
    private static Color fixColor(Color c) {
        if (ImageManager.isGrayBinded()) {
            ImageManager.unbindGray();
            ImageManager.setGrayBinded(true);
            int t = (c.getRed() + c.getGreen() + c.getGreen())/3;
            return new Color(t, t, t);
        }
        return c;
    }
}
